package com.ruoyi.system.service.impl;

import com.ruoyi.system.domain.SysContracts;
import com.ruoyi.system.domain.SysUserScok;
import com.ruoyi.system.service.ISysUserService;
import com.ruoyi.system.service.MatchingService;
import com.ruoyi.system.service.SysContractsService;
import com.ruoyi.system.service.SysUserScokService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Set;

@Service
public class MatchingServiceImpl implements MatchingService {
    @Autowired
    RedisTemplate redisTemplate;
    @Autowired
    SysContractsService contractsService;
    @Autowired
    ISysUserService userService;
    @Autowired
    SysUserScokService scokService;


    @PostConstruct
    public void preheat(){
        SysContracts contracts = new SysContracts();
        contracts.setStatus(0);
        List<SysContracts> sysContracts = contractsService.selectSysContractsList(contracts);
        for (SysContracts sysContract : sysContracts) {
            redisTemplate.opsForZSet().add("matchings:"+sysContract.getScokName()+"-"+sysContract.getFalg(),sysContract,sysContract.getScokPrice().doubleValue());
        }
    }

    @Transactional
    public void matching(SysContracts contracts, String key){
        Set<SysContracts> range = redisTemplate.opsForZSet().range(key, 0, -1);
        System.err.println(range);
        if (range!=null && range.size()>0){
            //预存储
            int contractsNum=contracts.getNum();
            for (SysContracts o : range) {
                if (contracts.getNum()==0){
//                  修改数据库--用户金额--今日委托状态--发送通知
                    contracts.setNum(contractsNum);
                    tongZhi(contracts);
                    System.err.println(contracts);
                    break;
                }
//                预存储
                int oNum=o.getNum();
//               买入
                if (contracts.getScokPrice().byteValue()>=o.getScokPrice().byteValue() && contracts.getFalg()==0 && contracts.getNum()>0){
                    buyAndSell(contracts, key, o, oNum);
                }else if (contracts.getScokPrice().byteValue()<=o.getScokPrice().byteValue() && contracts.getFalg()==1 && contracts.getNum()>0){
//              卖出
                    buyAndSell(contracts, key, o, oNum);
                }
            }
        }else {
//            redisTemplate.opsForValue().setIfAbsent()
            redisTemplate.opsForZSet().add("matchings:"+contracts.getScokName()+"-"+contracts.getFalg(),contracts,contracts.getScokPrice().doubleValue());
        }
    }

    private void buyAndSell(SysContracts contracts, String key, SysContracts o, int oNum) {
        if (contracts.getNum()>=o.getNum()){
            contracts.setNum(contracts.getNum()-o.getNum());
//                       移除redis
            redisTemplate.opsForZSet().remove(key,o,o.getScokPrice());
//                        修改数据库--用户金额--今日委托状态--发送通知(可调出)
            tongZhi(o);
        }else {
//                      买入股票未购买完全,导致卖出的数量还有剩余,所以先往redis里添加新的委托,然后删掉旧的委托,已达到更新redis的目的
            tongZhi(contracts);
            o.setNum(o.getNum()-contracts.getNum());
            redisTemplate.opsForZSet().add("matchings:"+o.getScokName()+"-"+o.getFalg(),o,o.getScokPrice().doubleValue());
            o.setNum(oNum);
            redisTemplate.opsForZSet().remove(key,o,o.getScokPrice());
            contracts.setNum(0);

        }
    }


    public void tongZhi(SysContracts contracts){
//            修改状态
        contractsService.entrustmentStatus(contracts.getId());
        if (contracts.getFalg()==0){
//            股票数量
            SysUserScok userScok = scokService.selectById(contracts.getUserId().longValue(), contracts.getStockId());
            if (userScok!=null){
//              有就修改字段
                userScok.setScokPrice(contracts.getScokPrice());
                userScok.setNum(userScok.getNum()+contracts.getNum());
                scokService.updateById(userScok);
            }else{
//                没有就添加数据
                SysUserScok sysUserScok = new SysUserScok(null,contracts.getUserId(),contracts.getStockId(),contracts.getUname(),contracts.getScokName(),contracts.getScokPrice(),contracts.getNum(),0,new Date());
                scokService.insertMySock(sysUserScok);
            }
        }else {
//            用户金额
            userService.userAmount(contracts.getUserId(),contracts.getScokPrice().multiply(new BigDecimal(contracts.getNum())));
        }
//            发送通知

    }
}
